unit uSBDUnit_TestPointIteration;
interface
uses uSBD_BaseTypes, uSBDUnit_TestScheduler, uSBD_ServiceProvider,
     uSBDUnit_TestNode_InternalSupport, uSBDUnit_Model;

type

TTestPointEnumerableGetter = class( TSBD_RefCountedCommonBase, ITestEnumerableGetter, ITestEnumerableGetterEx)
  private
    FValidEnableStates: BooleanSet;
    [Injection('EnumerationRoot')] FRootNode: ITestNode;

    function  CreateTestEnumerable: TTestEnumerable;
    procedure SetEnumerateOverEnabled( ValidEnableStates: BooleanSet);
    procedure SetRoot( const RootNode: ITestNode);

  protected
    class function  ExceptionClass: TSBDUnit_ExceptionClass;                           override;

  public
    [Configuration] constructor Create;
  end;

TSBDUnit_TestPointIteration = class( TSBDUnit_Exception) end;

procedure RegisterServices( const Registrar: IServiceProvider);
// ^-- Registers (ITestEnumerableGetter,'')


implementation




uses Generics.Collections, SysUtils, uSBDUnit_HierarchyToLinearView;

type
THiearchicalEnumerable = class( TTestEnumerable)
  private
    FValidEnableStates: BooleanSet;
    FRootNode: ITestNode;
    FIntfEnumerable: TInterfaceEnumerable;
  protected
    function DoGetEnumerator: TEnumerator<ITestPoint>; override;
  public
    constructor Create( EnableStates: BooleanSet; const RootNode: ITestNode;
                        const Converter1: IHierarchyToLinearView_Converter);
  end;

THiearchicalEnumerator = class( TEnumerator<ITestPoint>)
  private
    FIntfEnum: TEnumerator<IInterface>;
    FCursor: RTestPointCursor;

  protected
    function DoGetCurrent: ITestPoint; override;
    function DoMoveNext: Boolean; override;

  public
    constructor Create( IntfEnum1: TEnumerator<IInterface>);
  end;


procedure RegisterServices( const Registrar: IServiceProvider);
begin
TTestPointEnumerableGetter
  .RegisterThis( Registrar, ITestEnumerableGetter)
end;





{ TTestPointEnumerableGetter }

constructor TTestPointEnumerableGetter.Create;
begin
FValidEnableStates := [True]
end;

function TTestPointEnumerableGetter.CreateTestEnumerable: TTestEnumerable;
var
  Converter: IHierarchyToLinearView_Converter;
begin
AcquireService( IHierarchyToLinearView_Converter, Converter);
result := THiearchicalEnumerable.Create( FValidEnableStates, FRootNode, Converter)
end;

class function TTestPointEnumerableGetter.ExceptionClass: TSBDUnit_ExceptionClass;
begin
result := TSBDUnit_TestPointIteration
end;

procedure TTestPointEnumerableGetter.SetEnumerateOverEnabled(
  ValidEnableStates: BooleanSet);
begin
FValidEnableStates := ValidEnableStates
end;

procedure TTestPointEnumerableGetter.SetRoot( const RootNode: ITestNode);
begin
FRootNode := RootNode
end;

type
THerEnumIObj = class( TSBD_RefCountedCommonBase, IGenericHierarchy)
  private
    FOwner: THiearchicalEnumerable;
    function Root: IInterface;
    function CountChildren( const Parent: IInterface): integer;
    function ChildOf( const Parent: IInterface; ChildIdx: integer): IInterface;
    function ParentOf( const Child: IInterface): IInterface;
    function CanonicalForm: TGUID;

  public
    [Configuration('THiearchicalEnumerable-Friend')]
    Constructor Create( Owner1: THiearchicalEnumerable);
  end;
{ THiearchicalEnumerable }

constructor THiearchicalEnumerable.Create(
  EnableStates: BooleanSet; const RootNode: ITestNode;
  const Converter1: IHierarchyToLinearView_Converter);
var
  Hierarchy: IGenericHierarchy;
begin
FValidEnableStates := EnableStates;
FRootNode := RootNode;
Hierarchy := THerEnumIObj.Create( self);
FIntfEnumerable := Converter1.Enumerable( Hierarchy,
  function( const Datum1: IInterface; Datum2: pointer; const Node: IInterface): boolean
    var
      TestNode: ITestNode;
    begin
    result := Supports( Node, ITestPoint) and (
              (not Supports( Node, ITestNode, TestNode)) or
              (TestNode.Enabled in FValidEnableStates))
    end,
  nil, nil)
end;

function THiearchicalEnumerable.DoGetEnumerator: TEnumerator<ITestPoint>;
begin
result := THiearchicalEnumerator.Create( FIntfEnumerable.GetEnumerator)
end;

{ THiearchicalEnumerator }

constructor THiearchicalEnumerator.Create(
  IntfEnum1: TEnumerator<IInterface>);
begin
FIntfEnum := IntfEnum1;
FCursor.FCurrentNode := nil;
FCursor.FWithinNode.ResetCursor;
// TO DO
//RTestPointCursor = record
//    FCurrentNode: ITestNode;
//    FWithinNode: RTestPointCursorMemento;
//  end;

end;

function THiearchicalEnumerator.DoGetCurrent: ITestPoint;
begin
result := FCursor.FCurrentNode as ITestPoint
end;

function THiearchicalEnumerator.DoMoveNext: Boolean;
var
  TestPoint: ITestPoint;
  TestCase: ITestCaseEx;

  function GetNextTestPointAtNextTestCase: boolean;
  begin
  result := FIntfEnum.MoveNext;
  FCursor.FCurrentNode := FIntfEnum.Current as ITestNode;
  FCursor.FWithinNode.ResetCursor;
  if Supports( FCursor.FCurrentNode, ITestCaseEx, TestCase) then
      begin
      FCursor.FWithinNode.FRunCount := TestCase.GetRunCount;
      TestCase.SetCursorMemento( FCursor.FWithinNode)
      end
    else
      FCursor.FWithinNode.FRunCount := 0
  end;

begin
if not assigned( FCursor.FCurrentNode) or (FCursor.FWithinNode.FRunIdx >= FCursor.FWithinNode.FRunCount) then
    result := GetNextTestPointAtNextTestCase
  else if (FCursor.FWithinNode.FPhase = High( TTestPointPhase)) and
          (FCursor.FWithinNode.FRunIdx >= (FCursor.FWithinNode.FRunCount - 1)) then
    begin
    Inc( FCursor.FWithinNode.FRunIdx);
    result := GetNextTestPointAtNextTestCase
    end
  else if FCursor.FWithinNode.FPhase = High( TTestPointPhase) then
    begin
    result := True;
    FCursor.FWithinNode.FPhase := Low( TTestPointPhase);
    Inc( FCursor.FWithinNode.FRunIdx);
    if Supports( FCursor.FCurrentNode, ITestCaseEx, TestCase) then
      TestCase.SetCursorMemento( FCursor.FWithinNode)
    end
  else
    begin
    result := True;
    Inc( FCursor.FWithinNode.FPhase);
    if Supports( FCursor.FCurrentNode, ITestCaseEx, TestCase) then
      TestCase.SetCursorMemento( FCursor.FWithinNode)
    end
end;

{ THerEnumIObj }

constructor THerEnumIObj.Create( Owner1: THiearchicalEnumerable);
begin
FOwner := Owner1
end;

function THerEnumIObj.CanonicalForm: TGUID;
begin
result := ITestPoint
end;

function THerEnumIObj.ChildOf(
  const Parent: IInterface; ChildIdx: integer): IInterface;
var
  TestNode: ITestNode;
begin
if Supports( Parent, ITestNode, TestNode) and (ChildIdx >= 0) and
   (ChildIdx < TestNode.Count) then
    result := TestNode.Children[ ChildIdx]
  else
    result := nil
end;

function THerEnumIObj.CountChildren( const Parent: IInterface): integer;
var
  TestNode: ITestNode;
begin
if Supports( Parent, ITestNode, TestNode) then
    result := TestNode.Count
  else
    result := 0
end;

function THerEnumIObj.ParentOf( const Child: IInterface): IInterface;
var
  TestNode: ITestNode;
begin
if Supports( Child, ITestNode, TestNode) then
    result := TestNode.Parent
  else
    result := nil
end;

function THerEnumIObj.Root: IInterface;
begin
result := FOwner.FRootNode
end;

end.
